package com.iisigroup.project.statistics;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set; 
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 

/**
 * The Class ProjectEvalForRL.
 */
public class ProjectEvalForRL {
    
    /** The Constant folderPath. */
    private static final String folderPath = "/home/weblogic/Desktop/needAnalysis/" ;
    
    /** The Constant LOGGER. */
    private static final Logger LOGGER = LoggerFactory.getLogger(ProjectEvalForRL.class);
        
    private static final String clasPathExpr = ".*\\/src\\/main\\/java\\/(tw\\/gov\\/moi\\/.*.java)";
    
    
    /**
     * The main method.
     *
     * @param args the arguments
     * @throws IOException 
     */
    public static void main(String[] args)  {
        final ProjectEvalForRL aProjectEvalForRL =    new ProjectEvalForRL() ;
        /**
         * step 1. 掃描相依性library 輸出成文件清單
         * **/
//        aProjectEvalForRL.scanRL();
        
        /**
         * step 2. 整理相依性library 輸出成文件清單,轉化成影響範圍下游程式清單
         * **/
        final Map<String,Set<String>>  data =   aProjectEvalForRL.getRelationShip(folderPath);
        
        /**
         * step 3. 讀入版本程式碼變動清單
         * **/
       final List<String> discrepencyIs = aProjectEvalForRL.readDiscrepency();
       for(String className : discrepencyIs){
           if(StringUtils.isBlank(className)){
               continue;
           }
           Set<String> classSet =  data.get(className);
           if(CollectionUtils.isEmpty(classSet)){
               continue;
           }
           System.out.println("-------------------");
           System.out.println("異動className: "+className);
           classSet.remove(className);
           if(CollectionUtils.isNotEmpty(classSet)){
               System.out.println("受影響範圍的 class set size : "+classSet.size());
               for(String classNameSub : classSet){
                   
                   System.out.println("受影響範圍的classNameSub : "+classNameSub);
               }
           }
           
       }
      
       
       
        LOGGER.info("size: {}",data.size());
    }
    String extraxtForJava (final String line){
        final Matcher matcher = Pattern.compile(clasPathExpr).matcher(line);
        if(  matcher.find()){
            return matcher.group (matcher.groupCount());
        }
      return null;
    }
    public List<String> readDiscrepency() {
        InputStream discrepencyIs = null;
        final List<String> result = new ArrayList<String>();
        try {
            discrepencyIs = ProjectEvalForRL.class
                    .getResourceAsStream("discrepency");
            final List<String> list = IOUtils.readLines(discrepencyIs);
            
            for (String line : list){
               if(StringUtils.contains(line, "RL") ){
                   final String data = extraxtForJava(line);
                   if(StringUtils.isNotBlank(data)){
                       result.add(data.replace("/", ".").replace(".java", ""));
                       
                   }
               } 
                
            }
        } catch (IOException e) {
            LOGGER.error( e.getMessage(),e );
        } finally {
            if (discrepencyIs != null) {
                try {
                    discrepencyIs.close();
                } catch (IOException e) {
                    LOGGER.error( e.getMessage(),e );
                }
            }
        }

        return result;
    }
    /**
     * Gets the relation ship.
     * 如果key為異動的class ,則value是受到影響的class
     * @param folder the folder
     * @return the relation ship
     */
    public Map<String,Set<String>> getRelationShip(String folder){
        final Map<String,Set<String>>  result = new HashMap<String, Set<String>>();
        for(File file : new File(folder).listFiles()){
            try {
                List<String> unit = FileUtils.readLines( file );
                for(String className : unit){                   
                    Set<String> set = result.get(className);
                    if(set ==null ){
                        set = new HashSet<String>();
                    }
                    set.add(file.getName());
                    result.put(className, set);
                }
               
            } catch (IOException e) {
                LOGGER.error(e.getMessage() ,e );
            }
        }
        
        
        return result ; 
    }
    
    /**
     * Scan rl.
     * 將各自class會受哪一些class影響的清單輸出成為檔案
     */
    public void scanRL() {
        List<ClassLoader> classLoadersList = new LinkedList<ClassLoader>();
        classLoadersList.add(ClasspathHelper.contextClassLoader());
        classLoadersList.add(ClasspathHelper.staticClassLoader()); 

        final ConfigurationBuilder builder = new ConfigurationBuilder()
                .setScanners(new SubTypesScanner(false), new ResourcesScanner())
                .setUrls(
                        ClasspathHelper.forClassLoader(classLoadersList
                                .toArray(new ClassLoader[0])))
                .filterInputsBy(
                        new FilterBuilder()
                                .include(FilterBuilder.prefix("tw.gov.moi.rl"))
                                .excludePackage("tw.gov.moi.ae")
                                .excludePackage("tw.gov.moi.domain")
                                .excludePackage("tw.gov.moi.security")
                                .excludePackage("javax.servlet")
                                .excludePackage("tw.gov.moi.dao"));

        final Reflections reflections = new Reflections(builder);

        final Set<Class<? extends Object>> allClassesSet = reflections
                .getSubTypesOf(Object.class);        
       
        final  Iterator<Class<? extends Object>> iterator = allClassesSet.iterator();
        while(iterator.hasNext()){
            final Class<? extends Object> unitClass  =   iterator.next();
            if(unitClass!=null && unitClass.getCanonicalName() != null  ){
                ClassEval aClassEval = new ClassEval();
                
                final Set<String> set = aClassEval.getAllEffectClass(unitClass);
                final List<String> lines = new ArrayList<String>();
                for(String className : set){
                    lines.add(className);
                }
                try {
                    FileUtils.writeLines(new File(folderPath+unitClass.getCanonicalName()), lines);
                } catch (IOException e) {
                    LOGGER.error(e.getMessage() ,e );
                }
                
                iterator.remove();
                
            }else{
                iterator.remove();
            }
            
        }
        
    }

}
